package client

import (
	"bytes"
	"encoding/binary"
	"encoding/json"
	"errors"
	"tio-proxy-agent/core"
	"tio-proxy-agent/log"
)

type GioClientHandler struct{}

func (GioClientHandler) Decode(buffer *bytes.Buffer, readableLength int32, ctx *core.ChannelContext) (core.Packet, error) {
	optBuffer := bytes.NewBuffer(buffer.Bytes())

	if readableLength < 5 {
		return nil, nil
	}

	msgType, _ := optBuffer.ReadByte()

	bodyLenBytes := optBuffer.Next(4)
	bodyLenBytesPtr := bytes.NewBuffer(bodyLenBytes)
	var bodyLen int32
	_ = binary.Read(bodyLenBytesPtr, binary.BigEndian, &bodyLen)
	if bodyLen < 0 {
		return nil, errors.New("bodyLength [" + string(bodyLen) + "] is not right, remote:" + ctx.BindIp)
	}

	var needLen = 5 + bodyLen
	if readableLength-needLen < 0 {
		return nil, nil
	}

	var bodyBytes = make([]byte, bodyLen)
	_, _ = optBuffer.Read(bodyBytes)

	packet := &BsPacket{
		Type: msgType,
		Body: bodyBytes,
	}

	buffer.Next(int(needLen))

	return packet, nil
}

func (GioClientHandler) Encode(packet core.Packet, ctx *core.ChannelContext) *bytes.Buffer {
	buffer := bytes.NewBuffer([]byte{})
	buffer.WriteByte(packet.GetType())
	_ = binary.Write(buffer, binary.BigEndian, int32(len(packet.GetBody())))
	buffer.Write(packet.GetBody())
	return buffer
}

func (GioClientHandler) Handler(packet core.Packet, ctx *core.ChannelContext) {
	msgType := packet.GetType()
	log.SugarLogger.Info("收到消息，消息类型为:", msgType)
	switch msgType {
	case 1:
		body := TcpBody{}
		_ = json.Unmarshal(packet.GetBody(), &body)
		body.Handler()
		break
	case 4:
		body := TcpTunnelBody{}
		_ = json.Unmarshal(packet.GetBody(), &body)
		body.Handler()
		break
	case 6:
		body := ConnectSuccessBody{}
		_ = json.Unmarshal(packet.GetBody(), &body)
		body.Handler()
		break
	}
}

type GioClientForwardHandler struct {
	BsId string
}

func (gioClientForwardHandler *GioClientForwardHandler) Decode(buffer *bytes.Buffer, readableLength int32, ctx *core.ChannelContext) (core.Packet, error) {
	packet := &BsPacket{
		Type: 98,
		Body: buffer.Bytes(),
	}
	buffer.Next(buffer.Len())
	return packet, nil
}

func (gioClientForwardHandler *GioClientForwardHandler) Encode(packet core.Packet, ctx *core.ChannelContext) *bytes.Buffer {
	return bytes.NewBuffer(packet.GetBody())
}

func (gioClientForwardHandler *GioClientForwardHandler) Handler(packet core.Packet, ctx *core.ChannelContext) {
	tcpBody := &TcpBody{
		Bytes: packet.GetBody(),
		BsId:  gioClientForwardHandler.BsId,
	}
	tcpBodyByte, _ := json.Marshal(tcpBody)
	bsPacket := &BsPacket{
		Type: 2,
		Body: tcpBodyByte,
	}
	ChannelManage["proxy"].SendData <- bsPacket

}
